package top.lishuoboy.dependency.sb.sb;

import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.lang.ansi.AnsiColor;
import cn.hutool.core.lang.ansi.AnsiEncoder;
import cn.hutool.core.lang.ansi.AnsiStyle;
import cn.hutool.core.util.RuntimeUtil;
import cn.hutool.core.util.StrUtil;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ConfigurableApplicationContext;
import top.lishuoboy.dependency.base.lang.ansi.AnsiStylePlus;
import top.lishuoboy.dependency.base.net.MyNetUtil;
import top.lishuoboy.dependency.base.str.MyStrPool;

/**
 * SpringBoot工具
 *
 * @author lishuoboy
 * @date 2022-8-30
 */
@Slf4j
public class MySbUtil {

    /**
     * 启动 SB 并 输出 “访问地址”、“启动用时”
     *
     * @param path            拼接在url端口后面的路径
     * @param openUrl         打开url
     * @param printInternetIp 打印公网ip
     */
    public static ConfigurableApplicationContext run(Class clazz, String[] args, @NonNull String path, boolean printInternetIp, boolean openUrl) {
        TimeInterval timeInterval = new TimeInterval();

        ConfigurableApplicationContext context = SpringApplication.run(clazz, args);

        String duration = timeInterval.intervalPretty();
        String template = "http://{}:{}{}{}";
        String port = context.getEnvironment().getProperty("server.port", "8080");
        String contextPath = context.getEnvironment().getProperty("server.servlet.context-path", "");

        if (StrUtil.isNotBlank(path) && !path.startsWith("/")) {
            path = "/" + path;
        }
        if (StrUtil.isNotBlank(contextPath) && !contextPath.startsWith("/")) {
            contextPath = "/" + contextPath;
        }

        StringBuilder sb = new StringBuilder();
        sb.append(AnsiEncoder.encode(AnsiStylePlus.SLOW_BLINK, AnsiStyle.BOLD, AnsiColor.BRIGHT_BLUE, "====================启动成功====================")).append(MyStrPool.LF);
        sb.append(StrUtil.format("  localhost   {}", StrUtil.format(template, MyNetUtil.LOCALHOST, port, contextPath, path))).append(MyStrPool.LF);
        sb.append(StrUtil.format("  hostname    {}", StrUtil.format(template, MyNetUtil.getHostname(), port, contextPath, path))).append(MyStrPool.LF);
//        sb.append(StrUtil.format("  本地IPv4    {}", StrUtil.format(template, MyNetUtil.LOCAL_IP_V4, port, contextPath, path))).append(MyStrPool.LF);
//        sb.append(StrUtil.format("  本地IPv6    {}", StrUtil.format(template, "[" + MyNetUtil.LOCAL_IP_V6 + "]", port, contextPath, path))).append(MyStrPool.LF);
//        sb.append(StrUtil.format("  本地IPv6    {}", StrUtil.format(template, "[" + MyNetUtil.LOCAL_IP_V6_FULL + "]", port, contextPath, path))).append(MyStrPool.LF);
        for (String ipv4 : MyNetUtil.getIntranetIpv4s()) {
            sb.append(StrUtil.format("  内网IPv4    {}", StrUtil.format(template, ipv4, port, contextPath, path))).append(MyStrPool.LF);
        }
//        for (String ipv6 : MyNetUtil.getIntranetIpv6s()) {
//            sb.append(StrUtil.format("  内网IPv6    {}", StrUtil.format(template, "[" + ipv6 + "]", port, contextPath, path))).append(MyStrPool.LF);
//        }
        if (printInternetIp) {
            sb.append(StrUtil.format("  公网IPv4    {}", StrUtil.format(template, MyNetUtil.getInternetIpV4(2000), port, contextPath, path))).append(MyStrPool.LF);
//            sb.append(StrUtil.format("  公网IPv6    {}", StrUtil.format(template, "[" + MyNetUtil.getInternetIpV6(2000) + "]", port, contextPath, path))).append(MyStrPool.LF);
        }
        sb.append(StrUtil.format("  启动用时    {} (SpringBoot {})", timeInterval.intervalPretty(), duration)).append(MyStrPool.LF);
        sb.append(AnsiEncoder.encode(AnsiStylePlus.SLOW_BLINK, AnsiStyle.BOLD, AnsiColor.BRIGHT_BLUE, "====================start ok==================")).append(MyStrPool.LF);  // 用于启动成功标志，如需修改，需同步修改启动监控shell脚本。
        System.out.println(sb);

        if (openUrl) {
            RuntimeUtil.exec("cmd /c start " + StrUtil.format(template, MyNetUtil.LOCALHOST, port, contextPath, path));  // 打开网址
        }
        return context;
    }

    /** 启动 SB 并 输出 “访问地址”、“启动用时”。不打印公网ip，不打开网址 */
    public static ConfigurableApplicationContext run(Class clazz, String[] args) {
        return run(clazz, args, "", false, false);
    }

    /**
     * 启动 SB 并 输出 “访问地址”、“启动用时”。不打印公网ip，不打开网址
     *
     * @param path 拼接在url端口后面的路径
     */
    public static ConfigurableApplicationContext run(Class clazz, String[] args, String path) {
        return run(clazz, args, path, false, false);
    }

    /**
     * 启动 SB 并 输出 “访问地址”、“启动用时”。不打开网址
     *
     * @param printInternetIp 打印公网ip。默认false
     */
    public static ConfigurableApplicationContext run(Class clazz, String[] args, boolean printInternetIp) {
        return run(clazz, args, "", printInternetIp, false);
    }

    /**
     * 启动 SB 并 输出 “访问地址”、“启动用时”。不打开网址
     *
     * @param path            拼接在url端口后面的路径
     * @param printInternetIp 打印公网ip。默认false
     */
    public static ConfigurableApplicationContext run(Class clazz, String[] args, String path, boolean printInternetIp) {
        return run(clazz, args, path, printInternetIp, false);
    }
}
